package com.tcm.core.service;

import cn.hutool.core.util.ObjectUtil;
import com.base.core.exception.ServiceException;
import com.base.core.utils.R;
import com.base.genid.generator.UidGenerator;
import com.base.core.constant.BaseConstants;
import com.base.core.tree.TreeParser;
import com.base.core.dozer.DozerConvert;
import com.base.core.utils.ListUtils;
import com.tcm.core.domain.dto.DepartmentDTO;
import com.tcm.core.domain.entity.Department;
import com.tcm.core.domain.enums.BusinessCodeEnum;
import com.tcm.core.domain.vo.DepartmentVO;
import com.tcm.core.mapper.DepartmentMapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.List;

@DubboService(version = "0.0.1-alpha", retries = 3, timeout = 3000)
public class DepartmentServiceImpl implements DepartmentService {

    @Autowired
    private DepartmentMapper departmentMapper;

    @DubboReference(version = "0.0.1-beta",group = "cached-uid",check = false,retries = 3)
    private UidGenerator uidGenerator;

    private final TreeParser<DepartmentVO> parser = new TreeParser<>();

    /**
     * 获得一级子分类
     * @param parentId 父id
     * @return
     * @throws Exception
     */
    @Override
    public List<DepartmentVO> listSubDepartment(Long parentId) throws Exception {
        return listSubDepartment(parentId, false);
    }

    /**
     * 查询分类数据
     * @param id
     * @return
     */
    @Override
    public DepartmentVO findById(Long id){
        Department department = departmentMapper.findById(id);
        DepartmentVO departmentVo = null;
        if(ObjectUtil.isNotNull(department)){
            departmentVo = DozerConvert.copyProperties(department, DepartmentVO.class);
        }
        return departmentVo;
    }

    /**
     * 获得所有分类
     * @return
     * @throws Exception
     */
    @Override
    public List<DepartmentVO> listDepartment() throws Exception{
        List<Department> department = departmentMapper.listDepartment();
        List<DepartmentVO> departmentVOList = null;
        if(ListUtils.isNotEmpty(department)){
            departmentVOList = DozerConvert.copyList(department, DepartmentVO.class);
        }
        return departmentVOList;
    }


    /**
     * 转换为树形结构
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<DepartmentVO> listToTree() throws Exception {
        return parser.treeList(0L,listDepartment());
    }

    /**
     * 递归查询子类
     * @param parentId 父类id
     * @param recursive
     * @return
     * @throws Exception
     */
    @Override
    public List<DepartmentVO> listSubDepartment(Long parentId, boolean recursive) throws Exception {
        if(!recursive){
            List<Department> departments = departmentMapper.listChild(parentId);
            return DozerConvert.copyList(departments, DepartmentVO.class);
        }
        List<DepartmentVO> listDepartmentVO = DozerConvert.copyList(listDepartment(), DepartmentVO.class);
        return parser.findChildNodes(listDepartmentVO, parentId);
    }

    /**
     * 加载所有父分类
     * @param categoryId
     * @return
     * @throws Exception
     */
    @Override
    public List<DepartmentVO> loadParents(Long categoryId) throws Exception {
        List<DepartmentVO> departmentVOS = DozerConvert.copyList(listDepartment(), DepartmentVO.class);
        return parser.findParentNodes(departmentVOS, categoryId);
    }

    /**
     * 获取当前类别的所有父类别ID
     * @param categoryId
     * @return
     * @throws Exception
     */
    @Override
    public List<Long> listParentIds(Long categoryId) throws Exception {
        List<DepartmentVO> departmentVOS = DozerConvert.copyList(listDepartment(), DepartmentVO.class);
        return parser.findParentIds(departmentVOS, categoryId);
    }

    /**
     * 获得当前类别所有子类别ID
     * @param departmentId
     * @return
     * @throws Exception
     */
    @Override
    public List<Long> listChildIds(Long departmentId) throws Exception {
        List<DepartmentVO> departmentVOS = DozerConvert.copyList(listDepartment(), DepartmentVO.class);
        return parser.findChildNodeIds(departmentVOS, departmentId);
    }

    /**
     * 验证分类有效性
     *
     * @param departmentId
     * @return
     */
    @Override
    public DepartmentVO valid(Long departmentId) {
        // 校验分类是否存在
        Department department = departmentMapper.findById(departmentId);
        if (department == null) {
            R.throwFail(BusinessCodeEnum.DEPARTMENT_NOT_EXISTS);
        }
        //禁用的科室不可用
        if (BaseConstants.NO.equals(department.getStatus())) {
            R.throwFail(BusinessCodeEnum.DEPARTMENT_MUST_ENABLE);
        }
        //验证是否叶子分类
        List<Department> childCategory = departmentMapper.listChild(department.getId());
        if(childCategory != null && childCategory.size() > 0){
            R.throwFail(BusinessCodeEnum.DEPARTMENT_PARENT_CAN_NOT_BE_LEAF);
        }
        // 返回结果
        return DozerConvert.copyProperties(department, DepartmentVO.class);
    }

    /**
     * 创建分类
     *
     * @param departmentDTO
     * @return
     */
    @Override
    public int create(DepartmentDTO departmentDTO) throws ServiceException {
        //设置深度
        setDepartmentLevel(departmentDTO);
        // 保存到数据库
        Department department = DozerConvert.copyProperties(departmentDTO, Department.class);
        department.setId(uidGenerator.getUID());
        department.setCreateTime(LocalDateTime.now());
        department.setUpdateTime(LocalDateTime.now());
        return departmentMapper.insert(department);
    }

    /**
     * 更新分类
     *
     * @param departmentDTO
     * @return
     */
    @Override
    public int update(DepartmentDTO departmentDTO) {
        // 校验不能设置自己为父分类
        if (departmentDTO.getId().equals(departmentDTO.getParentId())) {
            R.throwFail(BusinessCodeEnum.DEPARTMENT_PARENT_NOT_SELF);
        }
        // 校验父分类是否存在

        if (!departmentDTO.getParentId().equals(0L)) {
            Department department = departmentMapper.findById(departmentDTO.getParentId());
            if(ObjectUtil.isEmpty(department)){
                R.throwFail(BusinessCodeEnum.DEPARTMENT_PARENT_NOT_EXISTS);
            }
        }
        //设置深度
        setDepartmentLevel(departmentDTO);
        // 更新到数据库
        Department department = DozerConvert.copyProperties(departmentDTO, Department.class);
        department.setUpdateTime(LocalDateTime.now());
        return departmentMapper.updateById(department);
        // TODO 操作日志
    }

    /**
     * 根据分类的parentId设置分类的level
     */
    private void setDepartmentLevel(DepartmentDTO departmentDTO) {
        //没有父分类时为一级分类
        if (departmentDTO.getParentId() == 0) {
            departmentDTO.setLevel(1);
        } else {
            //有父分类时选择根据父分类level设置
            Department parentDepartment = departmentMapper.findById(departmentDTO.getParentId());
            if (parentDepartment != null) {
                departmentDTO.setLevel((parentDepartment.getLevel() + 1));
            } else {
                departmentDTO.setLevel(1);
            }
        }
    }

    /**
     * 删除分类
     *
     * @param id
     * @return
     */
    @Override
    public int deleteLogicById(Long id) {
        // 校验分类是否存在
        Department department = departmentMapper.findById(id);
        if (department == null) {
            R.throwFail(BusinessCodeEnum.DEPARTMENT_NOT_EXISTS);
        }

        // TODO 是否需要判断下该分类下是否有商品
        // 是否有子类
        List<Department> departments = departmentMapper.listChild(id);
        if(!departments.isEmpty()){
            R.throwFail(BusinessCodeEnum.DEPARTMENT_CHILD_CATEGORY_EXISTS);
        }
        // 标记删除商品分类
        return departmentMapper.deleteLogicById(id);
        // TODO 操作日志
    }

}
